#include <linux/proc_fs.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <linux/string.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqreturn.h>
#include <linux/module.h>
#include <linux/device.h>


static int major;
static unsigned char buff[100];
static struct class *hello_class;


static int hello_open (struct inode *node, struct file *filp)
{
	printk("hello_open\n");
	printk("%s %s %d\n",__FILE__, __FUNCTION__, __LINE__);

	return 0;
}

static ssize_t hello_read (struct file *filp, char *buf, size_t size, loff_t *offset)
{
	size_t len = size > 100 ? 100 : size;
	printk("hello_read\n");

	//尝试不通过copy_to_user，能否直接打印应用程序传递过来的数组[失败，内核输出一堆错]
	//printk("buf args = %s\n",buf);   
	copy_to_user(buf, buff, len);
	return len;
}

static ssize_t hello_write (struct file *filp, const char *buf, size_t size, loff_t *offset)
{
	size_t len = size > 100 ? 100 : size;
	memset(buff, 0 ,sizeof(buff));
	printk("hello_write\n");
	copy_from_user(buff, buf, len);
	return len;
}

static int hello_release (struct inode *node, struct file *filp)
{
	printk("hello_release\n");
	return 0;
}

/*1.定义 file_operations 结构体*/
static const struct file_operations hello_drv = {
    .owner 		= THIS_MODULE,
	.read		= hello_read,
	.write		= hello_write,
	.open		= hello_open,
	.release    = hello_release,
};


/*2.register_chrdev*/

/*3.入口函数*/
static int hello_init(void)
{
	struct device *dev;

	//返回主设备号
	major = register_chrdev(0,"hello_drv",&hello_drv);

	/*在内核中创建设备*/
	hello_class = class_create(THIS_MODULE, "hello_class");
	if (IS_ERR(hello_class)) {
		printk("hello class create failed!\n");
	}

	/*在/dev下面创建设备节点*/
	dev = device_create(hello_class, NULL, major, NULL, "hello");
	if (IS_ERR(dev)) {
		printk("hello device_create  failed!\n");
	}
	return 0;
}

/*4.退出函数*/
static void hello_exit(void)
{
	//卸载设备
	unregister_chrdev(major,"hello_drv");

	//销毁设备
	device_destroy(hello_class, MKDEV(major, 0));
	//删除设备类
	class_destroy(hello_class);

	//删除注册的设备号
	// unregister_chrdev_region(major, 1);
}	

module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");

